package cn.donting.web.desktop.core.servlet;

import cn.donting.web.desktop.core.Application;
import cn.donting.web.desktop.core.app.AppGetting;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author donting
 * 2021-06-26 下午3:29
 */
@WebFilter(filterName = "AppIdRefererFilter", urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST})
@Slf4j
public class AppIdRefererFilter implements Filter {
    public static String REQUEST_APP_ID = AppGetting.REQUEST_APP_ID;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        // 放过websocket
        if ("websocket".equalsIgnoreCase(httpServletRequest.getHeader("Upgrade"))) {
            chain.doFilter(request, response);
            return;
        }
        Long appId = appId(httpServletRequest);
        request.setAttribute(REQUEST_APP_ID, appId + "");
        boolean isSendRedirect = isSendRedirect(httpServletRequest);
        if (isSendRedirect) {
            String sendDirURL = getSendDirURL(httpServletRequest, appId);
            httpServletResponse.sendRedirect(sendDirURL);
            return;
        }
        chain.doFilter(request, response);
    }


    private boolean isSendRedirect(HttpServletRequest request) {
        String method = request.getMethod();
        String accept = request.getHeader("Accept");
        if ("get".equalsIgnoreCase(method) && accept != null &&
                accept.contains("text/html") && request.getParameter("appId") == null
                && request.getHeader("appId") == null) {

            return true;
        }
        return false;
    }


    private String getSendDirURL(HttpServletRequest request, Long appId) {
        String queryString = request.getQueryString();
        if (queryString != null) {
            queryString = "?" + queryString;
        } else {
            queryString = "";
        }
        if (queryString == "") {
            queryString = "?appId=" + appId;
        } else {
            queryString = "&appId=" + appId;
        }
        return request.getRequestURI() + queryString;
    }


    public Long appId(HttpServletRequest request) {

        String appId = request.getParameter("appId");
        if (appId != null) {
            return Long.parseLong(appId);
        }
        appId = request.getHeader("appId");
        if (appId != null) {
            return Long.parseLong(appId);
        }
        if (request.getRequestURI().startsWith("/sys")) {
            return Application.sysAppId;
        }
        //http://127.0.0.1:8080/a/b?abc=1
        String referer = request.getHeader("Referer");
        Long refererAppId = getRefererAppId(referer);
//        log.warn("appId：{}", request.getRequestURL());
        return refererAppId;
    }

    private Long getRefererAppId(String referer) {
        if(referer==null){
            return Application.sysAppId;
        }
        String appId = getQueryString("appId", referer);
        if (appId == null) {
            log.warn("Referer not found appId");
            return Application.sysAppId;
        }
        return  Long.parseLong(appId);
    }


    private String getQueryString(String name,String queryString){
        String a=  ("[\\?\\&]"+name+"=([^\\&]+)");
        //http://127.0.0.1:8080/a/b?abc=1
        // 创建 Pattern 对象
        Pattern r = Pattern.compile(a);
        // 现在创建 matcher 对象
        Matcher m = r.matcher(queryString);
        if (m.find()) {
            String group = m.group();
           return group.split("=")[1];
        }
        else{
            return null;
        }
    }
}
